home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / extend.exe / EXTEND.PAS < prev    next >
Pascal/Delphi Source File  |  1992-12-06  |  9KB  |  201 lines

  1. {$I-,O-,R-}
  2. {$IFDEF VER70}
  3. {$Q-}
  4. {$ENDIF}
  5.  
  6. unit Extend;
  7.  
  8. { This unit allows a program to open more than the standard DOS maximum of 20
  9.   open files at one time.  You must also be sure to set a FILES=XX statement
  10.   in your CONFIG.SYS file.  This program installs a special interrupt handler
  11.   under DOS 2.x, some semi-documented features under DOS 3.x prior to
  12.   DOS 3.3 and the DOS extend files call under DOS 3.3 or later.  This
  13.   unit USES the DOS unit and should be used before any other units other than
  14.   the DOS unit.  This code was based upon earlier work by Randy Forgaard, Bela
  15.   Lubkin and Kim Kokkonen.  See EXTEND.DOC for more information.
  16.  
  17.   Scott Bussinger
  18.   Professional Practice Systems
  19.   110 South 131st Street
  20.   Tacoma, WA  98444
  21.   (206)531-8944
  22.   Compuserve [72247,2671] }
  23.  
  24. { ** Revision History **
  25.   1 EXTEND.PAS 9-Mar-89,`SCOTT' First version using TLIB -- Based on 3.2
  26.   2 EXTEND.PAS 15-Sep-89,`SCOTT'
  27.            Added SwapVectorsExtend procedure
  28.            Put handle table into DOS memory
  29.            Use DOS 3.3 extended handles function when available
  30.   3 EXTEND.PAS 2-Oct-89,`SCOTT'
  31.            Fixed bug in determining the DOS version
  32.   4 EXTEND.PAS 5-Oct-89,`SCOTT'
  33.            Yet another bug in the DosVersion detection
  34.   5 EXTEND.PAS 9-Oct-92,14:59:50,`SCOTT'
  35.            Added compiler check for compatibility with BP 7
  36.            Added support for protected mode operation
  37.   6 EXTEND.PAS 5-Dec-92,`SCOTT'
  38.            Complete compatibility with BP7 protected and real modes
  39.   ** Revision History ** }
  40.  
  41. { Version 3.2 --  9/25/1988 -- Added O- compiler directive to prevent overlaying
  42.                                Moved extended handle table off of heap to support overlay manager
  43.                                Used DosVersion from DOS unit
  44.                                Turned off Range and I/O checking directives
  45.                                Fix exit procedure to chain first rather than last
  46.                                Compiled EXTEND.ASM with TASM
  47.                                Moved USES statement to implementation section
  48.           3.1 --  4/21/1988 -- Removed compiler directives (just uses defaults)
  49.           3.0 -- 10/16/1987 -- Reworked as a UNIT for use with Turbo Pascal 4
  50.                                EXTEND.ASM reworked to be compatible with A86 assembler
  51.                                Added support for DOS 3.3
  52.           2.5 --  3/16/1987 -- EXTEND.ASM worked on by Kim Kokkonen and Brian Foley to work
  53.                                  with Turbo Extender and whittle off a few clock cycles
  54.           2.4 -- 12/16/1986 -- Fixed a problem with DUP under DOS 2.x
  55.                                Now allocates the new handle table on heap
  56.                                  under DOS 3.x (compatible with TDebug+)
  57.           2.3 -- 11/18/1986 -- EXTEND now only affects DOS calls made from
  58.                                  same code segment it was installed from (fixes
  59.                                  problems with EXEC and batch files and already
  60.                                  resident TSR programs
  61.           2.2 -- 10/04/1986 -- Fixed problem with EXEC function destroying all
  62.                                  registers including the stack
  63.                                Changed way that original handle number is kept
  64.                                Permit FORCEDUP to change a standard handle
  65.                                Improve some comments
  66.           2.1 -- 10/02/1986 -- Fixed problem of Turbo assuming the registers
  67.                                  valid after the DOS call
  68.           2.0 -- 10/01/1986 -- Initial release of interrupt handler version
  69.           1.5                  Last version of EXTEND.PAS using explicit
  70.                                  calls to extend files. }
  71.  
  72. interface
  73.  
  74. procedure SwapVectorsExtend;
  75.   { Swap interrupt vectors taken over by Extend unit with system vectors }
  76.  
  77. implementation
  78.  
  79. uses Dos,Shrink
  80.      {$IFDEF DPMI}
  81.      ,WinAPI
  82.      {$ENDIF}
  83.      ;
  84.  
  85. type HandleArray = array[0..254] of byte;        { Room for 255 handles }
  86.      HandleArrayPtr = ^HandleArray;
  87.  
  88. var ExitSave: pointer;                           { Previous exit procedure }
  89.  
  90. var OldInt21: pointer;                           { Save old INT 21 }
  91.  
  92. var DosMemory: pointer;                          { Pointer to memory gained from DOS }
  93.     OldHandleTable: HandleArrayPtr;              { Pointer to original table }
  94.     OldNumHandles: byte;                         { Original number of handles }
  95.  
  96. {$IFNDEF DPMI}
  97. {$L EXTEND }
  98. procedure ExtendInit; external;                  { Initialize interrupt handler }
  99. procedure ExtendHandler; external;               { Replacement INT 21 handler }
  100. {$ENDIF}
  101.  
  102. procedure SwapVectorsExtend;
  103.   { Swap interrupt vectors taken over by Extend unit with system vectors }
  104.   var TempVector: pointer;
  105.   begin
  106.   {$IFNDEF DPMI}                                 { This can't apply to a DPMI program }
  107.   if lo(DosVersion) = 2 then
  108.     begin
  109.     GetIntVec($21,TempVector);                   { Swap the INT 21 vectors }
  110.     SetIntVec($21,OldInt21);
  111.     OldInt21 := TempVector
  112.     end
  113.   {$ENDIF}
  114.   end;
  115.  
  116. procedure ExtendHandles;
  117.   { Install the extended handles interrupt.  No files (other than
  118.     standard handles) should be open when unit starts up. }
  119.   var DontCare: word;
  120.       Regs: Registers;
  121.       TempSelector: word;
  122.  
  123.   function Linear(P: pointer): longint;
  124.     { Convert a real pointer into a linear address }
  125.     type Split = record
  126.            Ofs: word;
  127.            Seg: word
  128.            end;
  129.     begin
  130.     Linear := (longint(Split(P).Seg) shl 4) + Split(P).Ofs
  131.     end;
  132.  
  133.   begin
  134.   {$IFNDEF DPMI}                                 { Can't run DOS 2 on a DPMI system }
  135.   if lo(DosVersion) = 2
  136.    then
  137.     begin
  138.     GetIntVec($21,OldInt21);                     { Install interrupt handler under DOS 2.x }
  139.     ExtendInit;                                  { Initialize the interrupt handler }
  140.     SetIntVec($21,@ExtendHandler)
  141.     end
  142.    else
  143.   {$ENDIF}
  144.     begin
  145.     DosNewShrink(DosMemory,sizeof(HandleArray));
  146.     if DosMemory <> nil then                     { There wasn't enough memory for a handle table, so just quit }
  147.       if (lo(DosVersion)>=4) or (hi(DosVersion)>=30) { Does this DOS version support the handles call? }
  148.        then
  149.         begin
  150.         DosDispose(DosMemory);                   { Free up the DOS memory block so that the next function will succeed }
  151.         fillchar(Regs,sizeof(Regs),0);           { To avoid protected mode problems }
  152.         with Regs do
  153.           begin
  154.           AH := $67;                             { Tell DOS to allow us 255 handles }
  155.           BX := 255;                             { KEEP THIS NUMBER ODD TO AVOID BUG IN SOME VERSIONS OF DOS 3.3!! }
  156.           MsDos(Regs)
  157.           end
  158.         end
  159.        else
  160.         begin
  161.         fillchar(DosMemory^,sizeof(HandleArray),$FF);     { Initialize new handles as unused }
  162.         OldNumHandles := mem[prefixseg:$0032];            { Get old table length }
  163.         mem[prefixseg:$0032] := sizeof(HandleArray);      { Set new table length }
  164.         {$IFDEF DPMI}
  165.         TempSelector := AllocSelector(0);
  166.         DontCare := SetSelectorBase(TempSelector,Linear(pointer(ptr(prefixseg,$0034)^)));
  167.         DontCare := SetSelectorLimit(TempSelector,256);
  168.         OldHandleTable := ptr(TempSelector,0);            { Save address of old table }
  169.         memw[prefixseg:$0034] := GetSelectorBase(seg(DosMemory^)) and $F; { Point to new handle table (offset) }
  170.         memw[prefixseg:$0036] := GetSelectorBase(seg(DosMemory^)) shr 4;  { Point to new handle table (segment) }
  171.         move(OldHandleTable^,DosMemory^,OldNumHandles);   { Copy the current handle table to the new handle table }
  172.         DontCare := FreeSelector(TempSelector)
  173.         {$ELSE}
  174.         OldHandleTable := pointer(ptr(prefixseg,$0034)^); { Save address of old table }
  175.         pointer(meml[prefixseg:$0034]) := DosMemory;      { Point to new handle table }
  176.         move(OldHandleTable^,DosMemory^,OldNumHandles)    { Copy the current handle table to the new handle table }